package top.lemna.generator;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.softdev.system.generator.entity.ClassInfo;
import com.softdev.system.generator.entity.ParamInfo;
import com.softdev.system.generator.util.TableParseUtil;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.io.file.FileReader;
import cn.hutool.core.io.file.FileWriter;
import cn.hutool.core.util.StrUtil;
import freemarker.template.TemplateException;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class GeneratorBySql {

	public static void main(String[] args) {
		String templatePath = args[0];// "src/main/resources/public/dubbo";
		String basePackage = args[1];// "top.lemna.kllm.base"
		String outPath = args[2];// "generate/ccc/"
		String file = args[3];// d:/hu/test.txt sql 文件
		GeneratorBySql generator = new GeneratorBySql();
		generator.generator(basePackage, templatePath, outPath, file);
	}

	void generator(String basePackage, String templatePath, String outPath, String sqlFile) {
		List<String> templateList = getTemplate(templatePath);
		List<String> sqlList = parseSQl(sqlFile);
		generator(templateList, sqlList, templatePath, outPath);
	}

	void generator(List<String> templateList, List<String> sqlList, String templatePath, String outPath) {
		for (String sql : sqlList) {
			System.out.println("sql "+ sql);
			Map<String, Object> params = getParams(sql);
			for (String template : templateList) {
				System.out.println("template "+ template);
				generator(params, templatePath, template, outPath);
			}
		}

	}

	List<String> getTemplate(String templatePath) {
		File path = new File(templatePath);
		List<File> loopFiles = FileUtil.loopFiles(path);
		List<String> list = loopFiles.stream().map(f -> f.getPath()).map(n -> n.replace(path.getPath(), ""))
				.collect(Collectors.toList());
		return list;
	}

	void generator(Map<String, Object> params, String templatePath, String templateName, String outPath) {
		try {
			String result = FreemarkerUtil.processString(templatePath, templateName, params);
			ClassInfo classInfo = (ClassInfo) params.get("classInfo");
			String file = getOutFileName(classInfo.getClassName(), templateName, outPath);
			if(FileUtil.exist(file))
			{
				FileUtil.del(file);
			}
			FileWriter writer = new FileWriter(file);
			writer.write(result);
		} catch (IORuntimeException | IOException | TemplateException e) {
			throw new RuntimeException("输出到文件时发生异常", e);
		}
	}

	Map<String, Object> getParams(String sql) {

		try {
			Map<String, Object> options = new HashMap<String, Object>();
			ParamInfo paramInfo = new ParamInfo();
			options.put("dataType", "sql");
			options.put("authorName", "");
			options.put("packageName", "");
			options.put("returnUtilSuccess", "ReturnT.success");
			options.put("returnUtilFailure", "ReturnT.error");
			options.put("isPackageType", true);
			options.put("isSwagger", true);
			options.put("isAutoImport", false);
			options.put("isWithPackage", false);
			options.put("isComment", true);
			options.put("isLombok", true);
			options.put("ignorePrefix", "sys_");
			options.put("tinyintTransType", "int");
			options.put("nameCaseType", "CamelCase");
			options.put("timeTransType", "Date");

			paramInfo.setOptions(options);
			paramInfo.setTableSql(sql);
			ClassInfo classInfo = TableParseUtil.processTableIntoClassInfo(paramInfo);

			options.put("classInfo", classInfo);
			options.put("tableName", classInfo == null ? System.currentTimeMillis() : classInfo.getTableName());

			return options;
		} catch (IOException e) {
			throw new RuntimeException("解析 SQL 时发生异常", e);
		}
	}

	/**
	 * 将sql 文件根据 create table 解析成多段sql 返回
	 * 
	 * @param file
	 * @return
	 */
	List<String> parseSQl(String file) {
		List<String> sqlList = new ArrayList<String>();
		FileReader fileReader = new FileReader(file);
		List<String> lines = fileReader.readLines();
		StringBuffer sb = new StringBuffer();
		for (String line : lines) {
			if (StrUtil.isEmpty(line)) {
				continue;
			}
			if (line.trim().toUpperCase().startsWith("CREATE")) {
				String sql = sb.toString();
				sb = new StringBuffer();
				if (StrUtil.isNotEmpty(sql) && sql.trim().startsWith("CREATE")) {
					sqlList.add(sql);
				}
			}
			sb.append(line);
		}

		String sql = sb.toString();
		if (StrUtil.isNotEmpty(sql) && sql.trim().startsWith("CREATE")) {
			sqlList.add(sql);
		}
		return sqlList;
	}

	static String getOutFileName(String className, String templateName, String outPath) {
		String template = templateName.replace("\\", "/").replace("aaaaa", "");// 用于处理实体类 类名即输出文件名的情况，
		int separatorIndex = template.lastIndexOf("/");
		if (separatorIndex == -1) {
			return outPath + "/" + className + templateName;
		}

		String path = template.substring(0, separatorIndex + 1);
		String name = template.substring(separatorIndex + 1, template.length());

		return outPath + path + className + name;

	}
}
